package cn.xingzitech.common.id.snowflake;

import cn.xingzitech.common.id.IIdGenerator;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 雪花算法工厂
 * @author Bulgat
 */
public class SnowFlakeFactory {
    /**
     * 默认数据中心id
     */
    private static final long DEFAULT_DATA_CENTER_ID = 1L;

    /**
     * 默认机器标识
     */
    private static final long DEFAULT_MACHINE_ID = 1L;

    /**
     * 默认的雪花算法句柄
     */
    private static final String DEFAULT_SNOW_FLAKE = "snow.flake";

    /**
     * 缓存雪花算法id生成器对象
     */
    private static ConcurrentHashMap<String,SnowFlakeIdGenerator> snowFlakeCache
            = new ConcurrentHashMap<>();

    /**
     * 通过数据中心id和机器标识获取雪花算法id生成器
     * @param datacenterId
     * @param machineId
     * @return SnowFlakeIdGenerator对象
     */
    public static SnowFlakeIdGenerator getSnowFlakeIdGenerator(long datacenterId,long machineId){
        return new SnowFlakeIdGenerator(datacenterId,machineId);
    }
    /**
     * 获取雪花算法id生成器
     * @return SnowFlakeIdGenerator对象
     */
    public static SnowFlakeIdGenerator getSnowFlakeIdGenerator(){
        return new SnowFlakeIdGenerator(DEFAULT_DATA_CENTER_ID,DEFAULT_MACHINE_ID);
    }
    /**
     * 从缓存中获取雪花算法id生成器
     * @return SnowFlakeIdGenerator对象
     */
    public static SnowFlakeIdGenerator getSnowFlakeIdGeneratorFromCache(){
        SnowFlakeIdGenerator idGenerator = snowFlakeCache.get(DEFAULT_SNOW_FLAKE);
        if(idGenerator == null){
            idGenerator=new SnowFlakeIdGenerator(DEFAULT_DATA_CENTER_ID,DEFAULT_MACHINE_ID);
            snowFlakeCache.put(DEFAULT_SNOW_FLAKE,idGenerator);
        }
        return idGenerator;
    }
    /**
     * 通过数据中心id和机器标识从缓存中获取雪花算法id生成器
     * @param datacenterId
     * @param machineId
     * @return SnowFlakeIdGenerator对象
     */
    public static SnowFlakeIdGenerator getSnowFlakeIdGeneratorFromCache(long datacenterId,long machineId){
        if (datacenterId>SnowFlakeIdGenerator.getMaxDataCenterNum()||datacenterId<0){
            throw new IllegalArgumentException("datacenterId can't be greater than MAX_DATACENTER_NUM or less than 0");
        }
        if (machineId>SnowFlakeIdGenerator.getMaxMachineNum()||machineId<0){
            throw new IllegalArgumentException("machineId can't be greater than MAX_MACHINE_NUM or less than 0");
        }
        String key=DEFAULT_SNOW_FLAKE.concat(".")
                .concat(String.valueOf(datacenterId)).concat(".")
                .concat(String.valueOf(machineId));
        SnowFlakeIdGenerator idGenerator = snowFlakeCache.get(key);
        if(idGenerator == null){
            idGenerator=new SnowFlakeIdGenerator(datacenterId,machineId);
            snowFlakeCache.put(key,idGenerator);
        }
        return idGenerator;
    }

    public static void main(String[] args) {
        Long dataCenterId = SnowFlakeLoader.getDataCenterId();
        Long machineId = SnowFlakeLoader.getMachineId();
        IIdGenerator<Long> idGenerator= SnowFlakeFactory.getSnowFlakeIdGeneratorFromCache(dataCenterId,machineId);
        Set<Long> set=new HashSet<>();
        for (int i = 0; i < 1000; i++) {
            Long id = idGenerator.nextId();
            if (set.contains(id)) {
                throw new RuntimeException("Id duplicated!");
            }
            set.add(id);
            System.out.println(id);
        }
    }
}
